home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1999 March / EnigmA AMIGA RUN 35 (1999)(G.R. Edizioni)(IT)[!][issue 1999-03].iso / earcd / devel / vbcc-ppc-src / vlink / t_elf64.c < prev    next >
C/C++ Source or Header  |  1999-01-01  |  47KB  |  1,473 lines

  1. /* $VER: vlink t_elf64.c V0.6a (19.12.98)
  2.  *
  3.  * This file is part of vlink, a portable linker for multiple
  4.  * object formats.
  5.  * Copyright (c) 1997-99  Frank Wille
  6.  *
  7.  * vlink is freeware and part of the portable and retargetable ANSI C
  8.  * compiler vbcc, copyright (c) 1995-99 by Volker Barthelmann.
  9.  * vlink may be freely redistributed as long as no modifications are
  10.  * made and nothing is charged for it. Non-commercial usage is allowed
  11.  * without any restrictions.
  12.  * EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE
  13.  * SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR.
  14.  *
  15.  *
  16.  * v0.6a (19.12.98) phx
  17.  *       Support for little endian object file formats.
  18.  *       ** t_elf64.c still doesn't work - don't activate it! **
  19.  * v0.6  (24.10.98) phx
  20.  *       .sdata/.sbss and .sdata2/.sbss2 will always be combined.
  21.  *       Each target defines their own base register section offsets.
  22.  *       Linking with shared objects is possible. Creating them is
  23.  *       a another story...
  24.  *       ** t_elf64.c still doesn't work - don't activate it! **
  25.  * v0.5d (22.08.98) phx
  26.  *       Faster memory allocation can be activated by #define FASTALLOC.
  27.  *       ** t_elf64.c still doesn't work - don't activate it! **
  28.  * v0.5  (27.06.98) phx
  29.  *       Target-specific linker symbol support: elf64_lnksym(),
  30.  *       elf64_setlnksym().
  31.  *       ** t_elf64.c still doesn't work - don't activate it! **
  32.  * v0.4  (05.06.98) phx
  33.  *       New FFF targetlink(). Currently no meaning for ELF.
  34.  *       ** t_elf64.c still doesn't work - don't activate it! **
  35.  * v0.0  (25.04.98) phx
  36.  *       File created.
  37.  */
  38.  
  39.  
  40. #if defined(ELF64_ALPHA)
  41. #define T_ELF64_C
  42. #include "vlink.h"
  43. #include "elf64.h"
  44. #if defined(ELF64_ALPHA)
  45. #include "rel_elfalpha.h"
  46. #endif
  47.  
  48. #define ELF_VER 1
  49.  
  50.  
  51. #ifdef ELF64_ALPHA
  52. static int alpha64_identify(char*,uint8 *,unsigned long);
  53. static void alpha64_readconv(struct GlobalVars *,struct LinkFile *);
  54. static void alpha64_readELF(struct GlobalVars *,struct LinkFile *,uint8 *);
  55. static unsigned long alpha64_secbase(struct GlobalVars *,char *);
  56. static uint8 alpha64_cmpsecflags(uint8,uint8);
  57. static struct Section *alpha64_bssdefault(struct ObjectUnit *);
  58. static int alpha64_targetlink(struct GlobalVars *,struct LinkedSection *,
  59.                               struct Section *);
  60. static struct Symbol *alpha64_lnksym(struct GlobalVars *,struct Section *,
  61.                                      struct XReference *);
  62. static void alpha64_setlnksym(struct GlobalVars *,struct Symbol *,
  63.                               struct XReference *);
  64. static void alpha64_relocs(struct GlobalVars *,uint8 *,struct ObjectUnit *,
  65.                            struct Elf64_Shdr *);
  66. static void alpha64_writeobject(struct GlobalVars *,FILE *);
  67. static void alpha64_writeshared(struct GlobalVars *,FILE *);
  68. static void alpha64_writeexec(struct GlobalVars *,FILE *);
  69. static uint8 alpha64_getrel(uint8,char *,uint32);
  70.  
  71. struct FFFuncs fff_elf64alpha = {
  72.   "elf64alpha",
  73.   alpha64_identify,
  74.   alpha64_readconv,
  75.   alpha64_secbase,
  76.   alpha64_cmpsecflags,
  77.   alpha64_bssdefault,
  78.   alpha64_targetlink,
  79.   alpha64_lnksym,
  80.   alpha64_setlnksym,
  81.   alpha64_writeobject,
  82.   alpha64_writeshared,
  83.   alpha64_writeexec,
  84.   0x7ff0,  /*@@@ I have no information */
  85.   NULL,
  86.   0 /* little endian */
  87. };
  88. #endif
  89.  
  90. /* small data sections */
  91. static char *sdata = ".sdata";
  92. static char *sbss = ".sbss";
  93. static char *sdata2 = ".sdata2";
  94. static char *sbss2 = ".sbss2";
  95.  
  96.  
  97. static int elf64le_identify(struct FFFuncs *,char *,struct Elf64_Ehdr *,
  98.                             unsigned long,unsigned char,unsigned char,
  99.                             uint16,uint32);
  100. static void elf64le_check_ar_type(struct FFFuncs *,char *,
  101.                                   struct Elf64_Ehdr *,unsigned char,
  102.                                   unsigned char,uint32,uint16,uint16,uint16);
  103. static char *elf64le_shstrtab(struct LinkFile *,struct Elf64_Ehdr *);
  104. static char *elf64le_strtab(struct LinkFile *,struct Elf64_Ehdr *,int);
  105. static struct Elf64_Sym *elf64le_symtab(struct LinkFile *,
  106.                                         struct Elf64_Ehdr *,int);
  107. static struct Elf64_Shdr *elf64le_shdr(struct LinkFile *lf,
  108.                                        struct Elf64_Ehdr *,uint16);
  109. static void elf64le_section(uint8 *,struct ObjectUnit *,
  110.                             struct Elf64_Shdr *,int);
  111. static void elf64le_symbols(struct GlobalVars *,uint8 *,struct ObjectUnit *,
  112.                             struct Elf64_Shdr *);
  113. static void elf64le_reloc(struct GlobalVars *,struct Elf64_Ehdr *,
  114.                           struct Section *,uint32,struct Elf64_Rela *,
  115.                           bool,uint8);
  116. static struct Section *elf64le_bssdefault(struct ObjectUnit *);
  117. static int elf64_targetlink(struct GlobalVars *,struct LinkedSection *,
  118.                             struct Section *);
  119. static struct Symbol *elf64_lnksym(struct GlobalVars *,struct Section *,
  120.                                    struct XReference *);
  121. static void elf64_setlnksym(struct GlobalVars *,struct Symbol *,
  122.                             struct XReference *);
  123. static void elf64le_header(FILE *,uint16,uint16,uint32,uint32,uint32,
  124.                            uint32,uint16,uint16,uint16);
  125. static void elf64le_writeshdrs(FILE *,uint32,uint32);
  126. static void elf64le_stdsymtab(struct GlobalVars *,uint8,uint8);
  127. static void elf64le_addsymlist(struct GlobalVars *,struct SymTabList *,
  128.                                uint8,uint8);
  129. static void elf64le_makeshdrs(struct GlobalVars *);
  130. static void elf64le_addrelocs(struct GlobalVars *,
  131.                               uint8 (*)(uint8,char *,uint32));
  132. static void elf64le_makeshstrtab(void);
  133. static void elf64le_makestrtab(void);
  134. static void elf64le_makesymtab(uint32);
  135. static struct ShdrNode *elf64le_addshdr(uint32,uint32,uint32,uint32,uint32,
  136.                                         uint32,uint32,uint32,uint32,uint32);
  137. static uint32 elf64le_addsym(struct SymTabList *,char *,uint32,uint32,
  138.                              uint8,uint8,uint16);
  139. static uint32 elf64le_findsym(struct SymTabList *,char *,uint16);
  140. static void elf64le_addrela(uint32,int32,uint32,uint8);
  141.  
  142. static void elf64_initlists(void);
  143. static struct ShdrNode *elf64_newshdr(void);
  144. static uint32 elf64_addshdrstr(char *);
  145. static uint32 elf64_addstr(char *);
  146. static uint32 elf64_addstrlist(struct StrTabList *,char *);
  147. static uint8 elf64_getinfo(struct Symbol *);
  148. static uint8 elf64_getbind(struct Symbol *);
  149. static uint16 elf64_getshndx(struct Symbol *,uint8);
  150. static void elf64_writesections(struct GlobalVars *,FILE *);
  151. static void elf64_writestrtab(FILE *,struct StrTabList *);
  152. static void elf64_writesymtab(FILE *,struct SymTabList *);
  153. static void elf64_writerelocs(struct GlobalVars *,FILE *);
  154.  
  155.  
  156. static char ELFid[4] = {   /* identification for all ELF files */
  157.   0x7f,'E','L','F'
  158. };
  159.  
  160. static struct ar_info ai;  /* for scanning library archives */
  161. static char *shstrtab;     /* section header string table */
  162. static char *nullstr = "";
  163.  
  164. /* static data required for output file generation */
  165. static struct list shdrlist;
  166. static struct list phdrlist;
  167. static struct list relalist;
  168. static struct SymTabList symlist;
  169. static struct StrTabList shstrlist;
  170. static struct StrTabList stringlist;
  171. static uint32 shdrindex;
  172. static uint32 symtabidx,shstrtabidx,strtabidx; /* indexes of Shdr names */
  173. static uint32 elfoffset;    /* current ELF file offset */
  174. static int secsyms;         /* offset to find section symbols by shndx */
  175.  
  176.  
  177.  
  178. /*****************************************************************/
  179. /*                          Read ELF                             */
  180. /*****************************************************************/
  181.  
  182.  
  183. #ifdef ELF64_ALPHA
  184.  
  185. static int alpha64_identify(char *name,uint8 *p,unsigned long plen)
  186. /* identify ELF-Alpha-64Bit-LittleEndian */
  187. {
  188.   return (elf64le_identify(&fff_elf64alpha,name,(struct Elf64_Ehdr *)p,plen,
  189.                            ELFCLASS64,ELFDATA2LSB,EM_ALPHA,ELF_VER));
  190. }
  191.  
  192.  
  193. static void alpha64_readconv(struct GlobalVars *gv,struct LinkFile *lf)
  194. /* Read elf64alpha executable / object / shared obj. */
  195. {
  196.   if (lf->type == ID_LIBARCH) {
  197.     if (ar_init(&ai,(char *)lf->data,lf->length,lf->filename)) {
  198.       while (ar_extract(&ai)) {
  199.         lf->objname = allocstring(ai.name);
  200.         alpha64_readELF(gv,lf,ai.data);
  201.       }
  202.     }
  203.     else
  204.       ierror("alpha64_readconv(): archive %s corrupted since last access",
  205.              lf->pathname);
  206.   }
  207.   else {
  208.     lf->objname = lf->filename;
  209.     alpha64_readELF(gv,lf,lf->data);
  210.   }
  211. }
  212.  
  213.  
  214. static void alpha64_readELF(struct GlobalVars *gv,struct LinkFile *lf,
  215.                             uint8 *elf)
  216. {
  217.   struct ObjectUnit *u;
  218.   struct Elf64_Ehdr *ehdr = (struct Elf64_Ehdr *)elf;
  219.   struct Elf64_Shdr *shdr;
  220.   uint16 i,num_shdr;
  221.  
  222.   if (lf->type == ID_LIBARCH)  /* check ar-member for correct format */
  223.     elf64le_check_ar_type(&fff_elf64alpha,lf->pathname,ehdr,ELFCLASS64,
  224.                           ELFDATA2LSB,ELF_VER,EM_ALPHA,EM_NONE,EM_NONE);
  225.  
  226.   shstrtab = elf64le_shstrtab(lf,ehdr);
  227.   u = create_objunit(lf,lf->objname);
  228.  
  229.   switch (read16le(ehdr->e_type)) {
  230.  
  231.     case ET_REL:  /* relocatable object file */
  232.       if (read16le(ehdr->e_phnum) > 0)
  233.         error(47,lf->pathname,lf->objname);  /* ignoring program hdr. tab */
  234.       num_shdr = read16le(ehdr->e_shnum);
  235.  
  236.       /* create vlink sections */
  237.       for (i=1; i<num_shdr; i++) {
  238.         shdr = elf64le_shdr(lf,ehdr,i);
  239.         switch (read32le(shdr->sh_type)) {
  240.           case SHT_PROGBITS:
  241.           case SHT_NOBITS:
  242.             elf64le_section(elf,u,shdr,i);  /* create a new section */
  243.           default:
  244.             break;
  245.         }
  246.       }
  247.  
  248.       /* parse the other section headers */
  249.       for (i=1; i<num_shdr; i++) {
  250.         shdr = elf64le_shdr(lf,ehdr,i);
  251.         switch (read32le(shdr->sh_type)) {
  252.           case SHT_NULL:
  253.           case SHT_STRTAB:
  254.           case SHT_PROGBITS:
  255.           case SHT_NOBITS:
  256.             break;
  257.           case SHT_SYMTAB:
  258.             elf64le_symbols(gv,elf,u,shdr);  /* symbol definitions */
  259.             break;
  260.           case SHT_REL:
  261.           case SHT_RELA:
  262.             alpha64_relocs(gv,elf,u,shdr);  /* relocation information */
  263.             break;
  264.           case SHT_NOTE:
  265.             ierror("alpha64_readELF(): %s: Section header type %d is "
  266.                    "currently not supported",lf->pathname,
  267.                    (int)read32le(shdr->sh_type));
  268.             break;
  269.           default:
  270.             /* section header type not needed in relocatable objects */
  271.             error(48,lf->pathname,read32le(shdr->sh_type),lf->objname);
  272.             break;
  273.         }
  274.       }
  275.       break;
  276.  
  277.     case ET_DYN:  /* shared object file */
  278.       num_shdr = read16le(ehdr->e_shnum);
  279.  
  280.       /* create vlink sections */
  281.       for (i=1; i<num_shdr; i++) {
  282.         shdr = elf64le_shdr(lf,ehdr,i);
  283.         switch (read32le(shdr->sh_type)) {
  284.           case SHT_PROGBITS:
  285.           case SHT_NOBITS:
  286.             elf64le_section(elf,u,shdr,i);  /* create a new section */
  287.           default:
  288.             break;
  289.         }
  290.       }
  291.  
  292.       /* parse the other section headers */
  293.       for (i=1; i<num_shdr; i++) {
  294.         shdr = elf64le_shdr(lf,ehdr,i);
  295.         switch (read32le(shdr->sh_type)) {
  296.           case SHT_NULL:
  297.           case SHT_STRTAB:
  298.           case SHT_PROGBITS:
  299.           case SHT_NOBITS:
  300.           case SHT_HASH:
  301.           case SHT_DYNAMIC:
  302.           case SHT_DYNSYM:
  303.             break;
  304.           case SHT_SYMTAB:
  305.             elf64le_symbols(gv,elf,u,shdr);  /* symbol definitions */
  306.             break;
  307.           case SHT_NOTE:
  308.             ierror("alpha64_readELF(): %s: Section header type %d is "
  309.                    "currently not supported",lf->pathname,
  310.                    (int)read32le(shdr->sh_type));
  311.             break;
  312.           default:
  313.             /* section header type not needed in shared objects */
  314.             error(60,lf->pathname,read32le(shdr->sh_type),lf->objname);
  315.             break;
  316.         }
  317.       }
  318.       break;
  319.  
  320.     case ET_EXEC: /* executable file */
  321.       /* @@@ */
  322.       ierror("alpha64_readELF(): %s: Executables are currently "
  323.              "not supported",lf->pathname);
  324.       break;
  325.  
  326.     default:
  327.       error(41,lf->pathname,lf->objname);  /* illegal fmt./file corrupted */
  328.       break;
  329.   }
  330.  
  331.   /* add new object unit to the appropriate list */
  332.   add_objunit(gv,u,FALSE);
  333. }
  334.  
  335.  
  336. static unsigned long alpha64_secbase(struct GlobalVars *gv,char *name)
  337. /* return default base address for a section with this name */
  338. {
  339.   return (0);  /* @@@ has to be fixed... */
  340. }
  341.  
  342.  
  343. static uint8 alpha64_cmpsecflags(uint8 oldflags,uint8 newflags)
  344. /* compare and verify target-specific section flags, */
  345. /* return 0xff if sections are incompatible, otherwise return new flags */
  346. {
  347.   return (oldflags|newflags);
  348. }
  349.  
  350.  
  351. static struct Section *alpha64_bssdefault(struct ObjectUnit *ou)
  352. /* Create a default BSS section for elfppc64be */
  353. {
  354.   return (elf64le_bssdefault(ou));
  355. }
  356.  
  357.  
  358. static int alpha64_targetlink(struct GlobalVars *gv,struct LinkedSection *ls,
  359.                               struct Section *s)
  360. /* returns 1, if target requires the combination of the two sections, */
  361. /* returns -1, if target don't want to combine them, */
  362. /* returns 0, if target doesn't care - standard linking rules are used. */
  363. {
  364.   return (elf64_targetlink(gv,ls,s));
  365. }
  366.  
  367.  
  368. static struct Symbol *alpha64_lnksym(struct GlobalVars *gv,
  369.                                      struct Section *sec,
  370.                                      struct XReference *xref)
  371. {
  372.   return (elf64_lnksym(gv,sec,xref));
  373. }
  374.  
  375.  
  376. static void alpha64_setlnksym(struct GlobalVars *gv,struct Symbol *xdef,
  377.                               struct XReference *xref)
  378. {
  379.   elf64_setlnksym(gv,xdef,xref);
  380. }
  381.  
  382.  
  383. /* @@@@ hier gehts weiter @@@@ */
  384. static void alpha64_relocs(struct GlobalVars *gv,uint8 *elf,
  385.                            struct ObjectUnit *ou,struct Elf64_Shdr *shdr)
  386. {
  387.   char *sec_name = shstrtab + read32le(shdr->sh_name);
  388.   struct LinkFile *lf = ou->lnkfile;
  389.   bool rela = read32le(shdr->sh_type) == SHT_RELA;
  390.   uint8 rtype,*data = elf + read32le(shdr->sh_offset);
  391.   unsigned long entsize = read32le(shdr->sh_entsize);
  392.   int nrelocs = (int)(read32le(shdr->sh_size) / (uint32)entsize);
  393.   uint32 symndx = read32le(shdr->sh_link);
  394.  
  395.   struct Section *s;
  396.  
  397.   if ((data < lf->data) || 
  398.       (data + read32le(shdr->sh_size) > lf->data + lf->length))
  399.     error(51,lf->pathname,"ppc64be reloc",lf->objname);  /* illegal offset */
  400.   if (!(s = find_sect_id(ou,read32le(shdr->sh_info))))
  401.     /* a section with this index doesn't exist! */
  402.     error(52,lf->pathname,sec_name,lf->objname,(int)read32le(shdr->sh_info));
  403.  
  404.   while (nrelocs--) {
  405.     rtype = R_NONE;
  406.     switch (ELF64_R_TYPE_LE(((struct Elf64_Rela *)data)->r_info)) {
  407.       case R_NONE:
  408.         break;  /* ignore */
  409.       case R_PPC_ADDR32:
  410.         rtype = R_ADDR32;
  411.         break;
  412.       case R_PPC_ADDR24:
  413.         rtype = R_ADDR26;
  414.         break;
  415.       case R_PPC_ADDR16:
  416.         rtype = R_ADDR16;
  417.         break;
  418.       case R_PPC_ADDR16_LO:
  419.         rtype = R_ADDR16_LO;
  420.         break;
  421.       case R_PPC_ADDR16_HI:
  422.         rtype = R_ADDR16_HI;
  423.         break;
  424.       case R_PPC_ADDR16_HA:
  425.         rtype = R_ADDR16_HA;
  426.         break;
  427.       case R_PPC_ADDR14:
  428.         rtype = R_ADDR14;
  429.         break;
  430.       case R_PPC_ADDR14_BRTAKEN:
  431.         rtype = R_ADDR14_BRTAKEN;
  432.         break;
  433.       case R_PPC_ADDR14_BRNTAKEN:
  434.         rtype = R_ADDR14_BRNTAKEN;
  435.         break;
  436.       case R_PPC_REL24:
  437.         rtype = R_REL26;
  438.         break;
  439.       case R_PPC_REL14:
  440.         rtype = R_REL14;
  441.         break;
  442.       case R_PPC_REL14_BRTAKEN:
  443.         rtype = R_REL14_BRTAKEN;
  444.         break;
  445.       case R_PPC_REL14_BRNTAKEN:
  446.         rtype = R_REL14_BRNTAKEN;
  447.         break;
  448.       case R_PPC_REL32:
  449.         rtype = R_REL32;
  450.         break;
  451.       case R_PPC_SDAREL16:
  452.         rtype = R_BASEREL16;
  453.         break;
  454.       case R_PPC_PASM_TOC16:
  455.         rtype = R_BASEREL16;
  456.         break;
  457.       default:
  458.         ierror("alpha64_relocs(): %s (%s): Reloc type %d in %s is currently "
  459.                "not supported",lf->pathname,lf->objname,
  460.                ELF64_R_TYPE_LE(((struct Elf64_Rela *)data)->r_info),
  461.                sec_name);
  462.         break;
  463.     }
  464.  
  465.     if (rtype > R_NONE)
  466.       elf64le_reloc(gv,(struct Elf64_Ehdr *)elf,s,symndx,
  467.                     (struct Elf64_Rela *)data,rela,rtype);
  468.     data += entsize;  /* next reloc */
  469.   }
  470.  
  471. }
  472.  
  473. #endif /* ELF64_ALPHA */
  474.  
  475.  
  476. static int elf64le_identify(struct FFFuncs *ff,char *name,
  477.                             struct Elf64_Ehdr *p,unsigned long plen,
  478.                             unsigned char class,unsigned char endian,
  479.                             uint16 machine,uint32 ver)
  480. /* check a possible ELF file against the requirements, then */
  481. /* return its type (object, library, shared object) */
  482. {
  483.   bool arflag = FALSE;
  484.  
  485.   if (plen < sizeof(struct Elf64_Ehdr))
  486.     return (ID_UNKNOWN);
  487.  
  488.   if (ar_init(&ai,(char *)p,plen,name)) {
  489.     /* library archive detected, extract 1st archive member */
  490.     arflag = TRUE;
  491.     if (!(ar_extract(&ai))) {
  492.       error(38,name);  /* Empty archive ignored */
  493.       return (ID_LIBARCH);
  494.     }
  495.     p = (struct Elf64_Ehdr *)ai.data;
  496.   }
  497.  
  498.   if (!strncmp(p->e_ident,ELFid,4)) {
  499.     /* ELF identification found */
  500.     if (p->e_ident[EI_CLASS]==class && p->e_ident[EI_DATA]==endian &&
  501.         p->e_ident[EI_VERSION]==(unsigned char)ver &&
  502.         read32le(p->e_version)==ver && read16le(p->e_machine)==machine) {
  503.       switch (read16le(p->e_type)) {
  504.         case ET_REL:
  505.           return (arflag ? ID_LIBARCH : ID_OBJECT);
  506.         case ET_EXEC:
  507.           if (arflag) /* no executables in library archives */
  508.             error(40,name,ff->tname);
  509.           return (ID_EXECUTABLE);
  510.         case ET_DYN:
  511.           if (arflag) /* no shared objects in library archives */
  512.             error(39,name,ff->tname);
  513.           return (ID_SHAREDOBJ);
  514.         default:
  515.           error(41,name,ff->tname);  /* illegal fmt. / file corrupted */
  516.           break;
  517.       }
  518.     }
  519.   }
  520.  
  521.   return (ID_UNKNOWN);
  522. }
  523.  
  524.  
  525. static void elf64le_check_ar_type(struct FFFuncs *ff,char *name,
  526.                                   struct Elf64_Ehdr *ehdr,unsigned char class,
  527.                                   unsigned char endian,uint32 ver,
  528.                                   uint16 mach1,uint16 mach2,uint16 mach3)
  529. /* check all library archive members before conversion */
  530. {
  531.   uint16 m = read16le(ehdr->e_machine);
  532.  
  533.   if (!strncmp(ehdr->e_ident,ELFid,4)) {
  534.     /* ELF identification found */
  535.     if (ehdr->e_ident[EI_CLASS]==class && ehdr->e_ident[EI_DATA]==endian &&
  536.         ehdr->e_ident[EI_VERSION]==(unsigned char)ver &&
  537.         read32le(ehdr->e_version)==ver && (m==mach1 || m==mach2 || m==mach3)) {
  538.       switch (read16le(ehdr->e_type)) {
  539.         case ET_REL:
  540.           return;
  541.         case ET_EXEC:  /* no executables in library archives */
  542.           error(40,name,ff->tname);
  543.           break;
  544.         case ET_DYN:  /* no shared objects in library archives */
  545.           error(39,name,ff->tname);
  546.           break;
  547.         default:  /* illegal fmt. / file corrupted */
  548.           break;
  549.       }
  550.     }
  551.   }
  552.   error(41,name,ff->tname);
  553. }
  554.  
  555.  
  556. static char *elf64le_shstrtab(struct LinkFile *lf,struct Elf64_Ehdr *ehdr)
  557. /* returns a pointer to the section header string table, if present, */
  558. /* or NULL, otherwise */
  559. {
  560.   uint16 i;
  561.   struct Elf64_Shdr *shdr;
  562.   char *stab;
  563.  
  564.   if (i = read16le(ehdr->e_shstrndx)) {
  565.     shdr = elf64le_shdr(lf,ehdr,i);
  566.     if (read32le(shdr->sh_type) != SHT_STRTAB)
  567.       error(45,lf->pathname,lf->objname);  /* illegal type */
  568.     stab = ((char *)ehdr) + read32le(shdr->sh_offset);
  569.     if (((uint8 *)stab < lf->data) || 
  570.         ((uint8 *)stab + read32le(shdr->sh_size) > lf->data + lf->length))
  571.       error(46,lf->pathname,lf->objname);  /* illegal offset */
  572.     else
  573.       return (stab);
  574.   }
  575.   return (NULL);
  576. }
  577.  
  578.  
  579. static char *elf64le_strtab(struct LinkFile *lf,
  580.                             struct Elf64_Ehdr *ehdr,int idx)
  581. /* returns a pointer to the string table */
  582. {
  583.   static char *tabname = "string";
  584.   struct Elf64_Shdr *shdr;
  585.   char *stab;
  586.  
  587.   shdr = elf64le_shdr(lf,ehdr,idx);
  588.   if (read32le(shdr->sh_type) != SHT_STRTAB)
  589.      error(50,lf->pathname,tabname,lf->objname);  /* illegal type */
  590.   stab = ((char *)ehdr) + read32le(shdr->sh_offset);
  591.   if (((uint8 *)stab < lf->data) || 
  592.       ((uint8 *)stab + read32le(shdr->sh_size) > lf->data + lf->length))
  593.     error(51,lf->pathname,tabname,lf->objname);  /* illegal offset */
  594.   return (stab);
  595. }
  596.  
  597.  
  598. static struct Elf64_Sym *elf64le_symtab(struct LinkFile *lf,
  599.                                         struct Elf64_Ehdr *ehdr,int idx)
  600. /* returns a pointer to the symbol table */
  601. {
  602.   static char *tabname = "symbol";
  603.   struct Elf64_Shdr *shdr;
  604.   struct Elf64_Sym *symtab;
  605.  
  606.   shdr = elf64le_shdr(lf,ehdr,idx);
  607.   if (read32le(shdr->sh_type) != SHT_SYMTAB)
  608.      error(50,lf->pathname,tabname,lf->objname);  /* illegal type */
  609.   symtab = (struct Elf64_Sym *)((uint8 *)ehdr + read32le(shdr->sh_offset));
  610.   if (((uint8 *)symtab < lf->data) || 
  611.       ((uint8 *)symtab + read32le(shdr->sh_size) > lf->data + lf->length))
  612.     error(51,lf->pathname,tabname,lf->objname);  /* illegal offset */
  613.   return (symtab);
  614. }
  615.  
  616.  
  617. static struct Elf64_Shdr *elf64le_shdr(struct LinkFile *lf,
  618.                                        struct Elf64_Ehdr *ehdr,uint16 idx)
  619. /* return pointer to section header #idx */
  620. {
  621.   struct Elf64_Shdr *shdr;
  622.  
  623.   if (idx < read16le(ehdr->e_shnum)) {
  624.     shdr = (struct Elf64_Shdr *)(((char *)ehdr) + ((read32le(ehdr->e_shoff) +
  625.            (uint32)read16le(ehdr->e_shentsize) * (uint32)idx)));
  626.     if (((uint8 *)shdr < lf->data) ||
  627.         (((uint8 *)shdr)+read16le(ehdr->e_shentsize) > lf->data+lf->length))
  628.       /* section header #x has illegal offset */
  629.       error(44,lf->pathname,(int)idx,lf->objname);
  630.     return (shdr);
  631.   }
  632.   else  /* Invalid ELF section header index */
  633.     error(43,lf->pathname,(int)idx,lf->objname);
  634.   return (NULL);  /* not reached, for compiler's sake */
  635. }
  636.  
  637.  
  638. static void elf64le_section(uint8 *elf,struct ObjectUnit *ou,
  639.                             struct Elf64_Shdr *shdr,int shndx)
  640. /* create a new section */
  641. {
  642.   char *sec_name = shstrtab + read32le(shdr->sh_name);
  643.   uint8 *data = elf + read32le(shdr->sh_offset);
  644.   unsigned long size = (unsigned long)read32le(shdr->sh_size);
  645.   uint32 f = read32le(shdr->sh_flags);
  646.   struct LinkFile *lf = ou->lnkfile;
  647.   uint8 type=ST_DATA,flags=0;
  648.   struct Section *s;
  649.  
  650.   if (read32le(shdr->sh_type) == SHT_NOBITS) {
  651.     data = NULL;
  652.     type = ST_UDATA;
  653.     flags |= SF_UNINITIALIZED;
  654.   }
  655.   else {
  656.     if (data+size > lf->data+lf->length)  /* illegal section offset */
  657.       error(49,lf->pathname,sec_name,lf->objname);
  658.   }
  659.   s = create_section(ou,sec_name,data,size);
  660.  
  661.   s->id = shndx;  /* use section header index for identification */
  662.   s->protection = SP_READ;
  663.   if ((f & SHF_EXECINSTR) && data) {
  664.     type = ST_CODE;
  665.     s->protection |= SP_EXEC;
  666.   }
  667.   if (f & SHF_WRITE)
  668.     s->protection |= SP_WRITE;
  669.   if (!(f & SHF_ALLOC))
  670.     flags |= SF_DISCARD;
  671.  
  672.   s->type = type;
  673.   s->flags = flags;
  674.   s->alignment = (uint8)shiftval(read32le(shdr->sh_addralign));
  675.   addtail(&ou->sections,&s->n);  /* add Section to ObjectUnit */
  676. }
  677.  
  678.  
  679. static void elf64le_symbols(struct GlobalVars *gv,uint8 *elf,
  680.                             struct ObjectUnit *ou,struct Elf64_Shdr *shdr)
  681. /* convert ELF symbol definitions into internal format */
  682. {
  683.   struct LinkFile *lf = ou->lnkfile;
  684.   uint8 *data = elf + read32le(shdr->sh_offset);
  685.   unsigned long entsize = read32le(shdr->sh_entsize);
  686.   int nsyms = (int)(read32le(shdr->sh_size) / (uint32)entsize);
  687.   char *strtab = elf64le_strtab(lf,(struct Elf64_Ehdr *)elf,
  688.                                 read32le(shdr->sh_link));
  689.   struct Section *sec,*firstsec;
  690.   struct Elf64_Sym *elfsym;
  691.  
  692.   if ((data < lf->data) || 
  693.       (data + read32le(shdr->sh_size) > lf->data + lf->length))
  694.     error(51,lf->pathname,"symbol",lf->objname);  /* illegal offset */
  695.  
  696.   if (listempty(&ou->sections))  /* not a single section? */
  697.     firstsec = elf64le_bssdefault(ou);
  698.   else
  699.     firstsec = (struct Section *)ou->sections.first;
  700.  
  701.   /* read ELF xdef symbols and convert to internal format */
  702.   while (--nsyms > 0) {
  703.     int shndx;
  704.     char *symname;
  705.     uint8 type,objinfo,objbind;
  706.  
  707.     elfsym = (struct Elf64_Sym *)(data += entsize);
  708.     symname = strtab + read32le(elfsym->st_name);
  709.     switch (shndx = (int)read16le(elfsym->st_shndx)) {
  710.       case SHN_UNDEF:
  711.         sec = NULL;  /* ignore xrefs for now */
  712.         break;
  713.       /* assign a section for ABS and COMMON symbols, to prevent */
  714.       /* accidental NULL-pointer references */
  715.       case SHN_ABS:
  716.         sec = firstsec;
  717.         type = SYM_ABS;
  718.         break;
  719.       case SHN_COMMON:
  720.         sec = firstsec;
  721.         type = SYM_COMMON;
  722.         break;
  723.       /* reloc symbols have a definite section to which they belong */
  724.       default:
  725.         if (!(sec = find_sect_id(ou,shndx))) {
  726.           /* a section with this index doesn't exist! */
  727.           if (ELF64_ST_TYPE(*elfsym->st_info) != STT_SECTION)
  728.             error(53,lf->pathname,symname,lf->objname,shndx);
  729.         }
  730.         type = SYM_RELOC;
  731.         break;
  732.     }
  733.  
  734.     if ((objinfo = ELF64_ST_TYPE(*elfsym->st_info)) == STT_SECTION)
  735.       sec = NULL;  /* ignore section defines - will be reproduced */
  736.  
  737.     if (sec) {
  738.       struct Symbol *sym;
  739.  
  740.       if (objinfo > STT_FILE) {
  741.         /* illegal symbol type */
  742.         error(54,lf->pathname,(int)objinfo,symname,lf->objname);
  743.         objinfo = STT_NOTYPE;
  744.       }
  745.       switch (ELF64_ST_BIND(*elfsym->st_info)) {
  746.         case STB_LOCAL:
  747.           objbind = SYMB_LOCAL;
  748.           break;
  749.         case STB_GLOBAL:
  750.           objbind = SYMB_GLOBAL;
  751.           break;
  752.         case STB_WEAK:
  753.           objbind = SYMB_WEAK;
  754.           break;
  755.         default:  /* illegal binding type */
  756.           error(55,lf->pathname,symname,ELF64_ST_BIND(*elfsym->st_info),
  757.                 lf->objname);
  758.           objbind = SYMB_LOCAL;
  759.           break;
  760.       }
  761.  
  762.       /* add a new symbol definition */
  763.       if (objbind == SYMB_LOCAL) {
  764.         /* always define local symbols - multiple defintions allowed */
  765.         addlocsymbol(gv,sec,symname,read32le(elfsym->st_value),type,0,
  766.                      objinfo,read32le(elfsym->st_size));
  767.       }
  768.       else {
  769.         if (sym = addsymbol(gv,sec,symname,read32le(elfsym->st_value),type,
  770.                             0,objinfo,objbind,read32le(elfsym->st_size))) {
  771.           /* symbol is multiply defined! */
  772.           struct LinkFile *lf2 = sym->relsect->obj->lnkfile;
  773.           char buf[256];  /* @@@ dangerous... */
  774.  
  775.           if (lf2->type == ID_LIBARCH)
  776.             sprintf(buf,"%s (%s)",lf2->filename,lf2->objname);
  777.           else
  778.             strcpy(buf,lf2->objname);
  779.           error(56,lf->pathname,symname,lf->objname,buf);
  780.         }
  781.       }
  782.     }
  783.   }
  784. }
  785.  
  786.  
  787. static void elf64le_reloc(struct GlobalVars *gv,struct Elf64_Ehdr *elf,
  788.                           struct Section *s,uint32 symndx,
  789.                           struct Elf64_Rela *rel,bool rela,uint8 rtype)
  790. /* Insert relocations, which are relative to a defined symbol, into */
  791. /* the section's reloc-list. If the symbol is undefined, create an */
  792. /* external reference on it, with the supplied relocation type. */
  793. {
  794.   struct LinkFile *lf = s->obj->lnkfile;
  795.   struct Elf64_Shdr *symhdr = elf64le_shdr(lf,elf,symndx);
  796.   struct Elf64_Sym *sym = elf64le_symtab(lf,elf,symndx) +
  797.                           ELF64_R_SYM_LE(rel->r_info);
  798.   uint32 offs = read32le(rel->r_offset);
  799.   uint32 shndx = (uint32)read16le(sym->st_shndx);
  800.   int32 a;
  801.  
  802.   /* if addend isn't defined in Reloc, read it from the section data */
  803.   if (rela)
  804.     a = (int32)read32le(rel->r_addend);
  805.   else
  806.     a = readsection(s->data+offs,rtype);
  807.  
  808.   if (shndx == SHN_UNDEF) {
  809.     /* undefined symbol - create external reference */
  810.     char *xrefname = elf64le_strtab(lf,elf,read32le(symhdr->sh_link)) +
  811.                                     read32le(sym->st_name);
  812.  
  813.     addxref(gv,s,xrefname,offs,rtype,relocsize(rtype),a);
  814.   }
  815.  
  816.   else if (ELF64_ST_TYPE(*sym->st_info) == STT_SECTION) {
  817.     /* a normal relocation, with an offset relative to a section base */
  818.  
  819.     addreloc(s,find_sect_id(s->obj,shndx),0,offs,rtype,a);
  820.   }
  821.  
  822.   else if (ELF64_ST_TYPE(*sym->st_info)<STT_SECTION && shndx<SHN_ABS) {
  823.     /* relocations, which are relative to a known symbol */
  824.  
  825.     addreloc(s,find_sect_id(s->obj,shndx),0,offs,rtype,
  826.              (int32)read32le(sym->st_value) + a);
  827.   }
  828.  
  829.   else
  830.     ierror("elf64le_reloc(): %s (%s): Only relocations which are relative "
  831.            "to a section, function or object are supported",
  832.            lf->pathname,lf->objname);
  833. }
  834.  
  835.  
  836. static struct Section *elf64le_bssdefault(struct ObjectUnit *ou)
  837. /* Create a default BSS section for ELF64 LittleEndian */
  838. {
  839.   static char *bssname = ".bss";
  840.   struct Section *s = create_section(ou,bssname,NULL,0);
  841.  
  842.   s->flags |= SF_UNINITIALIZED;
  843.   s->type = ST_UDATA;
  844.   s->protection = SP_READ | SP_WRITE;
  845.   s->alignment = 4;  /* @@@ */
  846.   return (s);
  847. }
  848.  
  849.  
  850. static int elf64_targetlink(struct GlobalVars *gv,struct LinkedSection *ls,
  851.                             struct Section *s)
  852. /* returns 1, if target requires the combination of the two sections, */
  853. /* returns -1, if target don't want to combine them, */
  854. /* returns 0, if target doesn't care - standard linking rules are used. */
  855. {
  856.   if (!gv->dest_object) {
  857.     if ((!strncmp(ls->name,sdata,6) && !strncmp(s->name,sbss,5)
  858.          && *(ls->name+6) == *(s->name+5)) ||
  859.         (!strncmp(ls->name,sbss,5) && !strncmp(s->name,sdata,6)
  860.          && *(ls->name+5) == *(s->name+6)))
  861.       /* .sdata/.sbss, .sdata2/.sbss2, etc. are always combined */
  862.       return (1);
  863.   }
  864.   return (0);
  865. }
  866.  
  867.  
  868. static struct Symbol *elf64_lnksym(struct GlobalVars *gv,
  869.                                      struct Section *sec,
  870.                                      struct XReference *xref)
  871. {
  872.   return (NULL);
  873. }
  874.  
  875.  
  876. static void elf64_setlnksym(struct GlobalVars *gv,struct Symbol *xdef,
  877.                               struct XReference *xref)
  878. {
  879. }
  880.  
  881.  
  882.  
  883. /*****************************************************************/
  884. /*                          Write ELF                            */
  885. /*****************************************************************/
  886.  
  887.  
  888. #ifdef ELF64_ALPHA
  889.  
  890. static void alpha64_writeshared(struct GlobalVars *gv,FILE *f)
  891. /* creates a target-elfppc64be shared object (which is pos. independant) */
  892. {
  893.   ierror("alpha64_writeshared(): Shared object generation has not "
  894.          "yet been implemented");
  895. }
  896.  
  897.  
  898. static void alpha64_writeobject(struct GlobalVars *gv,FILE *f)
  899. /* creates a target-elfppc64be relocatable object file */
  900. {
  901.   uint32 sh_off,shstrndx,stabndx;
  902.  
  903.   elf64_initlists();
  904.   elf64le_addsym(&symlist,nullstr,0,0,0,0,SHN_UNDEF);
  905.   if (gv->discard_local < DISLOC_ALL)
  906.     elf64le_stdsymtab(gv,STB_LOCAL,STT_FILE);
  907.  
  908.   elf64le_makeshdrs(gv);
  909.   if (gv->discard_local < DISLOC_ALL)
  910.     elf64le_stdsymtab(gv,STB_LOCAL,0);
  911.   symlist.global_index = symlist.nextindex;
  912.   if (gv->strip_symbols < STRIP_ALL) { /* although not recomm. for objects */
  913.     elf64le_stdsymtab(gv,STB_WEAK,0);
  914.     elf64le_stdsymtab(gv,STB_GLOBAL,0);
  915.   }
  916.   elf64le_addrelocs(gv,alpha64_getrel);
  917.  
  918.   shstrndx = shdrindex;
  919.   elf64le_makeshstrtab();
  920.   sh_off = elfoffset;
  921.   stabndx = shdrindex;
  922.   elfoffset += (shdrindex+2) * sizeof(struct Elf64_Shdr);
  923.   elf64le_makesymtab(shdrindex+1);
  924.   elf64le_makestrtab();
  925.  
  926.   elf64le_header(f,ET_REL,EM_PPC,0,0,sh_off,0,0,shdrindex,shstrndx);
  927.   elf64_writesections(gv,f);
  928.   elf64_writestrtab(f,&shstrlist);
  929.   fwrite_align(f,2,ftell(f));
  930.   elf64le_writeshdrs(f,elfoffset,stabndx);
  931.   elf64_writesymtab(f,&symlist);
  932.   elf64_writestrtab(f,&stringlist);
  933.   fwrite_align(f,2,ftell(f));
  934.   elf64_writerelocs(gv,f);
  935. }
  936.  
  937.  
  938. static void alpha64_writeexec(struct GlobalVars *gv,FILE *f)
  939. /* creates a target-elfppc64be executable file (with absolute addresses) */
  940. {
  941.   ierror("alpha64_writeexec(): Executable file generation has not "
  942.          "yet been implemented");
  943. }
  944.  
  945.  
  946. static uint8 alpha64_getrel(uint8 rtype,char *sname,uint32 offs)
  947. {
  948.   switch (rtype) {
  949.     case R_NONE:
  950.       break;
  951.     case R_ADDR32:
  952.       return (R_PPC_ADDR32);
  953.     case R_ADDR26:
  954.       return (R_PPC_ADDR24);
  955.     case R_ADDR16:
  956.       return (R_PPC_ADDR16);
  957.     case R_ADDR16_LO:
  958.       return (R_PPC_ADDR16_LO);
  959.     case R_ADDR16_HI:
  960.       return (R_PPC_ADDR16_HI);
  961.     case R_ADDR16_HA:
  962.       return (R_PPC_ADDR16_HA);
  963.     case R_ADDR14:
  964.       return (R_PPC_ADDR14);
  965.     case R_ADDR14_BRTAKEN:
  966.       return (R_PPC_ADDR14_BRTAKEN);
  967.     case R_ADDR14_BRNTAKEN:
  968.       return (R_PPC_ADDR14_BRNTAKEN);
  969.     case R_REL26:
  970.       return (R_PPC_REL24);
  971.     case R_REL14:
  972.       return (R_PPC_REL14);
  973.     case R_REL14_BRTAKEN:
  974.       return (R_PPC_REL14_BRTAKEN);
  975.     case R_REL14_BRNTAKEN:
  976.       return (R_PPC_REL14_BRNTAKEN);
  977.     case R_BASEREL16:
  978.       return (R_PPC_SDAREL16);
  979.     default:
  980.       /* unsupported relocation type */
  981.       error(32,fff_elf32ppcbe.tname,reloc_name[rtype],sname,offs);
  982.       break;
  983.   }
  984.   return (R_NONE);
  985. }
  986.  
  987. #endif /* ELF64_ALPHA */
  988.  
  989.  
  990. static void elf64le_header(FILE *f,uint16 type,uint16 mach,uint32 entry,
  991.                            uint32 phoff,uint32 shoff,uint32 flags,
  992.                            uint16 phnum,uint16 shnum,uint16 shstrndx)
  993. /* write ELF header for 32-bit big endian */
  994. {
  995.   struct Elf64_Ehdr eh;
  996.  
  997.   memset(&eh,0,sizeof(struct Elf64_Ehdr));
  998.   strncpy((char *)eh.e_ident,ELFid,4);
  999.   eh.e_ident[EI_CLASS] = ELFCLASS32;
  1000.   eh.e_ident[EI_DATA] = ELFDATA2MSB;
  1001.   eh.e_ident[EI_VERSION] = ELF_VER;
  1002.   write16le(eh.e_type,type);
  1003.   write16le(eh.e_machine,mach);
  1004.   write32le(eh.e_version,ELF_VER);
  1005.   write32le(eh.e_entry,entry);
  1006.   write32le(eh.e_phoff,phoff);
  1007.   write32le(eh.e_shoff,shoff);
  1008.   write32le(eh.e_flags,flags);
  1009.   write16le(eh.e_ehsize,sizeof(struct Elf64_Ehdr));
  1010.   write16le(eh.e_phentsize,phnum ? sizeof(struct Elf64_Phdr):0);
  1011.   write16le(eh.e_phnum,phnum);
  1012.   write16le(eh.e_shentsize,shnum ? sizeof(struct Elf64_Shdr):0);
  1013.   write16le(eh.e_shnum,shnum);
  1014.   write16le(eh.e_shstrndx,shstrndx);
  1015.   fwritex(f,&eh,sizeof(struct Elf64_Ehdr));
  1016. }
  1017.  
  1018.  
  1019. static void elf64le_writeshdrs(FILE *f,uint32 reloffset,uint32 stabndx)
  1020. /* write all section headers */
  1021. {
  1022.   struct ShdrNode *shn;
  1023.   uint32 type;
  1024.  
  1025.   while (shn = (struct ShdrNode *)remhead(&shdrlist)) {
  1026.     type = read32le(shn->s.sh_type);
  1027.     if (type == SHT_RELA || type == SHT_REL) {
  1028.       /* patch correct sh_offset and sh_link for reloc header */
  1029.       write32le(shn->s.sh_offset,read32le(shn->s.sh_offset)+reloffset);
  1030.       write32le(shn->s.sh_link,stabndx);
  1031.     }
  1032.     fwritex(f,&shn->s,sizeof(struct Elf64_Shdr));
  1033.   }
  1034. }
  1035.  
  1036.  
  1037. static void elf64le_stdsymtab(struct GlobalVars *gv,uint8 bind,uint8 type)
  1038. {
  1039.   elf64le_addsymlist(gv,&symlist,bind,type);
  1040. }
  1041.  
  1042.  
  1043. static void elf64le_addsymlist(struct GlobalVars *gv,struct SymTabList *sl,
  1044.                                uint8 bind,uint8 type)
  1045. /* add all symbols with specified bind and type to the ELF symbol list */
  1046. {
  1047.   struct LinkedSection *ls = (struct LinkedSection *)gv->lnksec.first;
  1048.   struct LinkedSection *nextls;
  1049.   struct Symbol *nextsym,*sym;
  1050.  
  1051.   while (nextls = (struct LinkedSection *)ls->n.next) {
  1052.     sym = (struct Symbol *)ls->symbols.first;
  1053.  
  1054.     while (nextsym = (struct Symbol *)sym->n.next) {
  1055.       uint8 symtype = elf64_getinfo(sym);
  1056.       uint8 symbind = elf64_getbind(sym);
  1057.  
  1058.       if (symbind == bind && (!type || (symtype == type))) {
  1059.         remnode(&sym->n);
  1060.         elf64le_addsym(sl,sym->name,sym->value,sym->size,
  1061.                        symbind,symtype,elf64_getshndx(sym,symtype));
  1062. #ifndef FASTALLOC
  1063.         free(sym);
  1064. #endif
  1065.       }
  1066.       sym = nextsym;
  1067.     }
  1068.     ls = nextls;
  1069.   }
  1070. }
  1071.  
  1072.  
  1073. static void elf64le_makeshdrs(struct GlobalVars *gv)
  1074. /* generate all ELF section headers */
  1075. {
  1076.   struct LinkedSection *ls = (struct LinkedSection *)gv->lnksec.first;
  1077.   struct LinkedSection *nextls;
  1078.   struct ShdrNode *shn;
  1079.   struct SymbolNode *sym;
  1080.   uint32 f;
  1081.   bool bss;
  1082.  
  1083.   /* offset, to find section-symbols by section header index */
  1084.   secsyms = (int)symlist.nextindex - (int)shdrindex;
  1085.  
  1086.   while (nextls = (struct LinkedSection *)ls->n.next) {
  1087.     ls->index = (int)shdrindex;
  1088.     bss = ls->type==ST_UDATA || (ls->flags&SF_UNINITIALIZED);
  1089.     f = (ls->flags & SF_DISCARD) ? 0 : SHF_ALLOC;
  1090.     if (ls->protection & SP_WRITE)
  1091.       f |= SHF_WRITE;
  1092.     if (ls->protection & SP_EXEC)
  1093.       f |= SHF_EXECINSTR;
  1094.     elf64le_addshdr(elf64_addshdrstr(ls->name),bss?SHT_NOBITS:SHT_PROGBITS,
  1095.                     f,0,elfoffset,ls->size,0,0,1<<(uint32)ls->alignment,0);
  1096.     if (!bss)
  1097.       elfoffset += ls->size;
  1098.  
  1099.     /* add section symbol (without name) */
  1100.     elf64le_addsym(&symlist,nullstr,0,0,STB_LOCAL,STT_SECTION,
  1101.                    (uint16)ls->index);
  1102.     ls = nextls;  /* next section */
  1103.   }
  1104. }
  1105.  
  1106.  
  1107. static void elf64le_addrelocs(struct GlobalVars *gv,
  1108.                               uint8 (*getrel)(uint8,char *,uint32))
  1109. /* creates relocations for all sections */
  1110. {
  1111.   struct LinkedSection *ls = (struct LinkedSection *)gv->lnksec.first;
  1112.   struct LinkedSection *nextls;
  1113.   struct Reloc *rel,*nextrel;
  1114.   struct XReference *xref,*nextxref;
  1115.   uint32 symidx,sroffs=0,roffs=0;
  1116.  
  1117.   while (nextls = (struct LinkedSection *)ls->n.next) {
  1118.     sroffs = roffs;
  1119.  
  1120.     /* relocations */
  1121.     rel = (struct Reloc *)ls->relocs.first;
  1122.     while (nextrel = (struct Reloc *)rel->n.next) {
  1123.       elf64le_addrela((uint32)rel->offset,rel->addend,
  1124.                       (uint32)(rel->relocsect.lnk->index + secsyms),
  1125.                       getrel(rel->type,ls->name,(uint32)rel->offset));
  1126.       roffs += gv->short_rel ?
  1127.                sizeof(struct Elf64_Rel) : sizeof(struct Elf64_Rela);
  1128.       rel = nextrel;
  1129.     }
  1130.  
  1131.     /* external references */
  1132.     xref = (struct XReference *)ls->xrefs.first;
  1133.     while (nextxref = (struct XReference *)xref->n.next) {
  1134.       /* undefined symbol */
  1135.       if (!(symidx = elf64le_findsym(&symlist,xref->name,SHN_UNDEF)))
  1136.         symidx = elf64le_addsym(&symlist,xref->name,0,0,STB_GLOBAL,
  1137.                                 STT_NOTYPE,SHN_UNDEF);
  1138.       /* symbol's relocation */
  1139.       elf64le_addrela((uint32)xref->offset,xref->addend,symidx,
  1140.                       getrel(xref->type,ls->name,(uint32)xref->offset));
  1141.       roffs += gv->short_rel ?
  1142.                sizeof(struct Elf64_Rel) : sizeof(struct Elf64_Rela);
  1143.       xref = nextxref;
  1144.     }
  1145.  
  1146.     if (roffs != sroffs) {
  1147.       /* create ".rel(a).name" header */
  1148.       char *relname = (char *)alloc(strlen(ls->name)+6);
  1149.  
  1150.       sprintf(relname,".%s%s",gv->short_rel ? "rel":"rela",ls->name);
  1151.       elf64le_addshdr(elf64_addshdrstr(relname),
  1152.                       gv->short_rel ? SHT_REL:SHT_RELA,
  1153.                       0,0,sroffs,roffs-sroffs,0,(uint32)ls->index,4,
  1154.                       gv->short_rel ? sizeof(struct Elf64_Rel) : 
  1155.                                       sizeof(struct Elf64_Rela));
  1156.       /* sroffs is relative and will be corrected later */
  1157.       /* sh_link will be initialized, when .symtab exists */
  1158.     }
  1159.     ls = nextls;  /* next section */
  1160.   }
  1161. }
  1162.  
  1163.  
  1164. static void elf64le_makeshstrtab()
  1165. /* creates .shstrtab */
  1166. {
  1167.   elf64le_addshdr(shstrtabidx,SHT_STRTAB,0,0,elfoffset,
  1168.                   shstrlist.nextindex,0,0,1,0);
  1169.   elfoffset += shstrlist.nextindex;
  1170.   elfoffset += align(elfoffset,2);
  1171. }
  1172.  
  1173.  
  1174. static void elf64le_makestrtab()
  1175. /* creates .strtab */
  1176. {
  1177.   elf64le_addshdr(strtabidx,SHT_STRTAB,0,0,elfoffset,
  1178.                   stringlist.nextindex,0,0,1,0);
  1179.   elfoffset += stringlist.nextindex;
  1180.   elfoffset += align(elfoffset,2);
  1181. }
  1182.  
  1183.  
  1184. static void elf64le_makesymtab(uint32 strtabindex)
  1185. /* creates .symtab */
  1186. {
  1187.   elf64le_addshdr(symtabidx,SHT_SYMTAB,0,0,elfoffset,
  1188.                   symlist.nextindex * sizeof(struct Elf64_Sym),
  1189.                   strtabindex,symlist.global_index,4,
  1190.                   sizeof(struct Elf64_Sym));
  1191.   elfoffset += symlist.nextindex * sizeof(struct Elf64_Sym);
  1192. }
  1193.  
  1194.  
  1195. static struct ShdrNode *elf64le_addshdr(uint32 name,uint32 type,uint32 flags,
  1196.                                         uint32 addr,uint32 offset,
  1197.                                         uint32 size,uint32 link,uint32 info,
  1198.                                         uint32 align,uint32 entsize)
  1199. {
  1200.   struct ShdrNode *shn = elf64_newshdr();
  1201.  
  1202.   write32le(shn->s.sh_name,name);
  1203.   write32le(shn->s.sh_type,type);
  1204.   write32le(shn->s.sh_flags,flags);
  1205.   write32le(shn->s.sh_addr,addr);
  1206.   write32le(shn->s.sh_offset,offset);
  1207.   write32le(shn->s.sh_size,size);
  1208.   write32le(shn->s.sh_link,link);
  1209.   write32le(shn->s.sh_info,info);
  1210.   write32le(shn->s.sh_addralign,align);
  1211.   write32le(shn->s.sh_entsize,entsize);
  1212.   return (shn);
  1213. }
  1214.  
  1215.  
  1216. static uint32 elf64le_addsym(struct SymTabList *sl,char *name,uint32 value,
  1217.                              uint32 size,uint8 bind,uint8 type,uint16 shndx)
  1218. /* add a new ELF symbol, return its symbol table index */
  1219. {
  1220.   struct SymbolNode **chain = &sl->hashtab[elf_hash(name) % SYMHTABSIZE];
  1221.   struct SymbolNode *sym;
  1222.  
  1223.   while (sym = *chain)
  1224.     chain = &sym->hashchain;
  1225.   /* new symbol table entry */
  1226.   *chain = sym = alloczero(sizeof(struct SymbolNode));
  1227.   sym->name = name;
  1228.   sym->index = sl->nextindex++;
  1229.   addtail(&sl->l,&sym->n);
  1230.   write32le(sym->s.st_name,elf64_addstr(name));
  1231.   write32le(sym->s.st_value,value);
  1232.   write32le(sym->s.st_size,size);
  1233.   *sym->s.st_info = ELF64_ST_INFO(bind,type);
  1234.   write16le(sym->s.st_shndx,shndx);
  1235.   return (sym->index);
  1236. }
  1237.  
  1238.  
  1239. static uint32 elf64le_findsym(struct SymTabList *sl,char *name,uint16 shndx)
  1240. /* find an ELF symbol by its name and shndx */
  1241. /* return its symbol table index, index=0 means 'not found' */
  1242. {
  1243.   struct SymbolNode **chain = &sl->hashtab[elf_hash(name) % SYMHTABSIZE];
  1244.   struct SymbolNode *sym;
  1245.  
  1246.   while (sym = *chain) {
  1247.     if (!strcmp(name,sym->name))
  1248.       if (read16le(sym->s.st_shndx) == shndx)
  1249.         return (sym->index);
  1250.     chain = &sym->hashchain;
  1251.   }
  1252.   return (0);
  1253. }
  1254.  
  1255.  
  1256. static void elf64le_addrela(uint32 offs,int32 addend,uint32 sym,uint8 type)
  1257. {
  1258.   struct RelaNode *rn = alloc(sizeof(struct RelaNode));
  1259.  
  1260.   write32le(rn->r.r_offset,offs);
  1261.   write32le(rn->r.r_addend,addend);
  1262.   ELF64_R_INFO_LE(rn->r.r_info,sym,(uint32)type);
  1263.   addtail(&relalist,&rn->n);
  1264. }
  1265.  
  1266.  
  1267. static void elf64_initlists()
  1268. /* initialize section header, program header, relocation, symbol, */
  1269. /* string and section header string lists */
  1270. {
  1271.   static struct StrTabNode *str_hashtab[STRHTABSIZE];
  1272.   static struct StrTabNode *shstr_hashtab[SHSTRHTABSIZE];
  1273.   static struct SymbolNode *sym_hashtab[SYMHTABSIZE];
  1274.  
  1275.   elfoffset = sizeof(struct Elf64_Ehdr);
  1276.   initlist(&shdrlist);
  1277.   initlist(&phdrlist);
  1278.   initlist(&relalist);
  1279.   shdrindex = 0;
  1280.  
  1281.   initlist(&symlist.l);
  1282.   symlist.hashtab = sym_hashtab;
  1283.   memset(sym_hashtab,0,SYMHTABSIZE*sizeof(struct SymbolNode *));
  1284.   symlist.nextindex = symlist.global_index = 0;
  1285.  
  1286.   initlist(&shstrlist.l);
  1287.   initlist(&stringlist.l);
  1288.   shstrlist.hashtab = shstr_hashtab;
  1289.   stringlist.hashtab = str_hashtab;
  1290.   shstrlist.nextindex = stringlist.nextindex = 0;
  1291.   stringlist.htabsize = STRHTABSIZE;
  1292.   shstrlist.htabsize = SHSTRHTABSIZE;
  1293.   memset(shstr_hashtab,0,SHSTRHTABSIZE*sizeof(struct StrTabNode *));
  1294.   memset(str_hashtab,0,STRHTABSIZE*sizeof(struct StrTabNode *));
  1295.  
  1296.   elf64_addshdrstr(nullstr);  /* first string is always "" */
  1297.   symtabidx = elf64_addshdrstr(".symtab");
  1298.   strtabidx = elf64_addshdrstr(".strtab");
  1299.   shstrtabidx = elf64_addshdrstr(".shstrtab");
  1300.   elf64_addstr(nullstr);
  1301.   elf64_newshdr();          /* first Shdr is always zero */
  1302. }
  1303.  
  1304.  
  1305. static struct ShdrNode *elf64_newshdr()
  1306. {
  1307.   struct ShdrNode *s = alloczero(sizeof(struct ShdrNode));
  1308.  
  1309.   addtail(&shdrlist,&s->n);
  1310.   ++shdrindex;
  1311.   return (s);
  1312. }
  1313.  
  1314.  
  1315. static uint32 elf64_addshdrstr(char *s)
  1316. {
  1317.   return (elf64_addstrlist(&shstrlist,s));
  1318. }
  1319.  
  1320.  
  1321. static uint32 elf64_addstr(char *s)
  1322. {
  1323.   return (elf64_addstrlist(&stringlist,s));
  1324. }
  1325.  
  1326.  
  1327. static uint32 elf64_addstrlist(struct StrTabList *sl,char *s)
  1328. /* add a new string to an ELF string table and return its index */
  1329. {
  1330.   struct StrTabNode **chain = &sl->hashtab[elf_hash(s) % sl->htabsize];
  1331.   struct StrTabNode *sn;
  1332.  
  1333.   /* search string in hash table */
  1334.   while (sn = *chain) {
  1335.     if (!strcmp(s,sn->str))
  1336.       return (sn->index);  /* it's already in, return index */
  1337.     chain = &sn->hashchain;
  1338.   }
  1339.  
  1340.   /* new string table entry */
  1341.   *chain = sn = alloc(sizeof(struct StrTabNode));
  1342.   sn->hashchain = NULL;
  1343.   sn->str = s;
  1344.   sn->index = sl->nextindex;
  1345.   addtail(&sl->l,&sn->n);
  1346.   sl->nextindex += (uint32)strlen(s) + 1;
  1347.   return (sn->index);
  1348. }
  1349.  
  1350.  
  1351. static uint8 elf64_getinfo(struct Symbol *sym)
  1352. {
  1353.   uint8 type;
  1354.  
  1355.   switch (sym->info) {
  1356.     case SYMI_NOTYPE:
  1357.       type = STT_NOTYPE;  /* @@@ Is this allowed? */
  1358.       break;
  1359.     case SYMI_OBJECT:
  1360.       type = STT_OBJECT;
  1361.       break;
  1362.     case SYMI_FUNC:
  1363.       type = STT_FUNC;
  1364.       break;
  1365.     case SYMI_SECTION:
  1366.       ierror("elf64le_addsymlist(): STT_SECTION symbol detected");
  1367.       type = STT_SECTION;
  1368.       break;
  1369.     case SYMI_FILE:
  1370.       type = STT_FILE;
  1371.       break;
  1372.     default:
  1373.       ierror("elf64_getinfo(): Illegal symbol info: %d",(int)sym->info);
  1374.       break;
  1375.   }
  1376.   return (type);
  1377. }
  1378.  
  1379.  
  1380. static uint8 elf64_getbind(struct Symbol *sym)
  1381. {
  1382.   uint8 bind;
  1383.  
  1384.   switch (sym->bind) {
  1385.     case SYMB_LOCAL:
  1386.       bind = STB_LOCAL;
  1387.       break;
  1388.     case SYMB_GLOBAL:
  1389.       bind = STB_GLOBAL;
  1390.       break;
  1391.     case SYMB_WEAK:
  1392.       bind = STB_WEAK;
  1393.       break;
  1394.     default:
  1395.       ierror("elf64_getbind(): Illegal symbol binding: %d",(int)sym->bind);
  1396.       break;
  1397.   }
  1398.   return (bind);
  1399. }
  1400.  
  1401.  
  1402. static uint16 elf64_getshndx(struct Symbol *sym,uint8 symtype)
  1403. {
  1404.   uint16 shndx;
  1405.  
  1406.   switch (sym->type) {
  1407.     case SYM_UNDEF:
  1408.       shndx = SHN_UNDEF;
  1409.       break;
  1410.     case SYM_ABS:
  1411.       shndx = SHN_ABS;
  1412.       break;
  1413.     case SYM_RELOC:
  1414.       if (symtype > STT_FUNC)
  1415.         ierror("elf64_getshndx(): %s is relocatable, but not a "
  1416.                "function or object (type %d)",sym->name,(int)symtype);
  1417.       shndx = (uint16)sym->relsect->lnksec->index;
  1418.       break;
  1419.     case SYM_COMMON:
  1420.       shndx = SHN_COMMON;
  1421.       break;
  1422.     default:
  1423.       ierror("elf64_getshndx(): Illegal symbol type: %d",(int)sym->type);
  1424.       break;
  1425.   }
  1426.   return (shndx);
  1427. }
  1428.  
  1429.  
  1430. static void elf64_writesections(struct GlobalVars *gv,FILE *f)
  1431. /* write all linked sections */
  1432. {
  1433.   struct LinkedSection *ls = (struct LinkedSection *)gv->lnksec.first;
  1434.   struct LinkedSection *nextls;
  1435.  
  1436.   while (nextls = (struct LinkedSection *)ls->n.next) {
  1437.     if (!(ls->flags & SF_UNINITIALIZED))
  1438.       fwritex(f,ls->data,ls->size);
  1439.     ls = nextls;
  1440.   }
  1441. }
  1442.  
  1443.  
  1444. static void elf64_writestrtab(FILE *f,struct StrTabList *sl)
  1445. {
  1446.   struct StrTabNode *stn;
  1447.  
  1448.   while (stn = (struct StrTabNode *)remhead(&sl->l))
  1449.     fwritex(f,stn->str,strlen(stn->str)+1);
  1450. }
  1451.  
  1452.  
  1453. static void elf64_writesymtab(FILE *f,struct SymTabList *sl)
  1454. {
  1455.   struct SymbolNode *sym;
  1456.  
  1457.   while (sym = (struct SymbolNode *)remhead(&sl->l))
  1458.     fwritex(f,&sym->s,sizeof(struct Elf64_Sym));
  1459. }
  1460.  
  1461.  
  1462. static void elf64_writerelocs(struct GlobalVars *gv,FILE *f)
  1463. {
  1464.   struct RelaNode *rn;
  1465.  
  1466.   while (rn = (struct RelaNode *)remhead(&relalist))
  1467.     fwritex(f,&rn->r,gv->short_rel ? sizeof(struct Elf64_Rel) : 
  1468.                                      sizeof(struct Elf64_Rela));
  1469. }
  1470.  
  1471.  
  1472. #endif
  1473.